'''
Created on 8 juin 2013

@author: Nils Amiet
'''

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import networkx as nx
import math
import random
from django.http.response import HttpResponse

class GraphPlotter():
    '''Class used to plot networkx graphs with matplotlib'''
    
    def __init__(self, dpi=100, width=1600, height=900):
        self.dpi = dpi
        self.width = width
        self.height = height
        
    def setFigureSize(self, figure):
        w = int(self.width/self.dpi)
        h = int(self.height/self.dpi)
        figure.set_size_inches(w, h)
        
    def bipartiteNodePositions(self, graph):
        '''Compute layout with nice node positions for a bipartite graph'''
        bipartiteAttributes = nx.get_node_attributes(graph, "bipartite")
        
        partitionA = [node for node in graph.nodes() if bipartiteAttributes[node] is 0] # bipartite=0
        partitionB = [node for node in graph.nodes() if bipartiteAttributes[node] is not 0] # bipartite=1
        
        pos = {}
        
        for node in partitionA:
            xCoord = random.uniform(0, 0.2) # random position on the left side
            yCoord = random.uniform(0, 1)
            pos[node] = [xCoord, yCoord]
            
        for node in partitionB:
            xCoord = random.uniform(0.8, 1) # random position on the right side
            yCoord = random.uniform(0, 1)
            pos[node] = [xCoord, yCoord]
        
        return pos
        
    def memoryPlot(self, graph, bipartite=False, pos=None, nodeSizes=None, nodeColor='r', nodeLabel="Nodes", nodeLabel2="Nodes 2", edgeLabel="Edges"):
        '''Plots the network using matplotlib'''
        if pos is None:
#             pos = nx.spring_layout(graph)
            pos = nx.random_layout(graph)
                
        nodeSize = 25
        edgeWidth = 0.5
        
        if nodeSizes is not None:
            nodeSize = nodeSizes

        figure = plt.figure()
        rect = (0,0,1,1)
        ax = figure.add_axes(rect)
        matplotlib.pyplot.axis("off")
                
        if bipartite:
            bipartiteAttributes = nx.get_node_attributes(graph, "bipartite")
            
            users = [node for node in graph.nodes() if bipartiteAttributes[node] is 0] # bipartite=0
            discussions = [node for node in graph.nodes() if bipartiteAttributes[node] is not 0] # bipartite=1
            
            nx.draw_networkx_nodes(graph, ax=ax, pos=pos, node_size=nodeSize, nodelist=users, label=nodeLabel)
            nx.draw_networkx_nodes(graph, ax=ax, pos=pos, node_size=nodeSize, nodelist=discussions, node_color='b', label=nodeLabel2)
            nx.draw_networkx_edges(graph, ax=ax, pos=pos, width=edgeWidth, label=edgeLabel)
            
            userCount = len(users)
            discussionCount = len(discussions)
            edgeCount = len(graph.edges())
            graphInfo = str() + "%s users\n%s discussions\n%s edges\n" % (userCount, discussionCount, edgeCount)
            figure.text(0,0, graphInfo)
        else:
            nx.draw_networkx_nodes(graph, ax=ax, pos=pos, node_size=nodeSize, nodelist=graph.nodes(), node_color=nodeColor, label=nodeLabel)
            nx.draw_networkx_edges(graph, ax=ax, pos=pos, width=edgeWidth, label=edgeLabel)
            
            nodeCount = len(graph.nodes())
            edgeCount = len(graph.edges())
            graphInfo = str() + "%s nodes \n%s edges\n" % (nodeCount, edgeCount)
            figure.text(0,0, graphInfo)
            
        try:
            matplotlib.pyplot.legend()
        except:
            print("Warning: drawing legend failed")
                
        response = HttpResponse(content_type="image/png")
        self.setFigureSize(figure)
        figure.savefig(response, format='png', dpi=self.dpi, bbox_inches='tight')
        return response
        
class TwoDimensionalValuesPlotter():
    '''Class used to plot 2D datasets with matplotlib'''
    
    def __init__(self, dpi=100, width=1600, height=900):
        self.dpi = dpi
        self.width = width
        self.height = height
        
    def setFigureSize(self, figure):
        w = int(self.width/self.dpi)
        h = int(self.height/self.dpi)
        figure.set_size_inches(w, h)
        
    def plot(self, xValues, yValues, filename, xlabel, ylabel):
        figure = plt.figure()
        
        subplot = figure.add_subplot(1, 1, 1)
        subplot.set_xlabel(xlabel)
        subplot.set_ylabel(ylabel)
        subplot.grid(True)
        
        subplot.plot(xValues, yValues)
        
        self.setFigureSize(figure)
        plt.savefig(filename, dpi=self.dpi)
    
    def memoryPlotMultipleDatasets(self, datasets, xlabel, ylabel):
        '''Plots multiple curves on the same chart'''
        figure = plt.figure()
        
        datasetCount = len(datasets)
        width = math.ceil(math.sqrt(datasetCount))
        for datasetId, dataset in enumerate(datasets):
            subplot = figure.add_subplot(width, width, datasetId)
            
            subplot.set_xlabel(xlabel)
            subplot.set_ylabel(ylabel)
            subplot.grid(True)
            
            title = dataset[0]
            
            xValues = dataset[1][0]
            
            yValues = dataset[1][1]
            subplot.set_title(title)
            
            subplot.plot(xValues, yValues)
        
            # plot title/axis/labels font size
            for item in ([subplot.title, subplot.xaxis.label, subplot.yaxis.label] + subplot.get_xticklabels() + subplot.get_yticklabels()):
                item.set_fontsize(8)
        
        figure.tight_layout()
        
        response = HttpResponse(content_type="image/png")
        self.setFigureSize(figure)
        figure.savefig(response, format='png')
        
        return response
    
    def memoryPlotMultipleDatasetsMultidimensional(self, datasetsList, xlabel, ylabel):
        '''Plots multiple subcharts on the same chart'''
        figure = plt.figure()
        
        datasets = zip(*datasetsList)
        legendData = [1,2] # dummy values
        
        datasetCount = len(datasets)
        width = math.ceil(math.sqrt(datasetCount))
        for datasetId, datasetTuple in enumerate(datasets):
            subplot = figure.add_subplot(width, width, datasetId)
            
            subplot.set_xlabel(xlabel)
            subplot.set_ylabel(ylabel)
            subplot.grid(True)
            
            title = datasetTuple[0][0]
            
            for num, dataset in enumerate(datasetTuple):
                xValues = dataset[1][0]
                
                yValues = dataset[1][1]
                subplot.set_title(title)
                
                legendData[num], = subplot.plot(xValues, yValues, label=num)
        
            # plot title/axis/labels font size
            for item in ([subplot.title, subplot.xaxis.label, subplot.yaxis.label] + subplot.get_xticklabels() + subplot.get_yticklabels()):
                item.set_fontsize(8)
        
        figure.tight_layout()
        figure.legend(legendData, ["equal time intervals", "equal reply count intervals"], loc="lower left", prop={"size": 6})
        
        response = HttpResponse(content_type="image/png")
        self.setFigureSize(figure)
        figure.savefig(response, format='png')
        return response